package main

import (
	"encoding/json"
	"fmt"
	"github.com/opdss/go-helper/path"
	"github.com/opdss/version"
	"github.com/spf13/cobra"
	"github.com/starmotioncf/common/cfgstruct"
	"github.com/starmotioncf/common/log"
	"github.com/starmotioncf/common/process"
	"github.com/starmotioncf/soutchatcmd/main/wire"
	"go.uber.org/zap"
	"os"
	"path/filepath"
)

var (
	cfg Config
)

var (
	configFile string
	rootCmd    = &cobra.Command{
		Use:   "soutchat",
		Short: "soutchat server",
	}
	runCmd = &cobra.Command{
		Use:   "run",
		Short: "运行",
		RunE:  cmdRun,
	}
	configCmd = &cobra.Command{
		Use:   "config",
		Short: "查看当前所有配置",
		RunE:  cmdConfig,
	}
	setupCmd = &cobra.Command{
		Use:         "setup",
		Short:       "初始化配置",
		RunE:        cmdSetup,
		Annotations: map[string]string{"type": "setup"},
	}
	versionCmd = &cobra.Command{
		Use:   "version",
		Short: "查看版本信息",
		RunE:  cmdVersion,
	}
)

// @title sout API
// @version v1.0.0
// @description   soutchat 接口文档
// @description   接口文档地址：https://api-test.sout.chat/swagger/index.html
// @description   开发规范：https://uir05jpuax4.feishu.cn/wiki/DYj5wSJAeihhbfk5MkjcrEoQnWc?fromScene=spaceOverview
// @description   测试接口地址：https://api-test.sout.chat/
// @description   生产接口地址：https://api.sout.chat/
// @description
// @description  约定规范
// @description   1. 接口统一采用RESTful风格
// @description   2. 接口请求参数和响应参数名统一驼峰规则，首字母小写
// @description   3. 接口路径统一小写下划线风格
// @description   4. 授权认证采用基于jwt的Bearer认证方案
// @securityDefinitions.apikey Bearer
// @in header
// @name Authorization
// @description 请在请求头中添加Authorization字段，值为Bearer + 空格 + 你的token
// @description 例如：Authorization: Bearer 123456
func main() {
	defaultConfig := path.ApplicationDir("soutchat", process.DefaultCfgFilename)
	cfgstruct.SetupFlag(rootCmd, &configFile, "config", defaultConfig, "配置文件")
	//根据环境读取默认配置
	defaults := cfgstruct.DefaultsFlag(rootCmd)
	//当前程序所在目录
	currentDir, _ := filepath.Abs(filepath.Dir(os.Args[0]))
	rootDir := cfgstruct.ConfigVar("ROOT", currentDir)
	//设置系统的HOME变量
	envHome := cfgstruct.ConfigVar("HOME", os.Getenv("HOME"))
	rootCmd.AddCommand(runCmd)
	rootCmd.AddCommand(configCmd)
	rootCmd.AddCommand(setupCmd)
	rootCmd.AddCommand(versionCmd)
	process.Bind(runCmd, &cfg, defaults, cfgstruct.ConfigFile(configFile), envHome, rootDir)
	process.Bind(configCmd, &cfg, defaults, cfgstruct.ConfigFile(configFile), envHome, rootDir)
	process.Bind(setupCmd, &cfg, defaults, cfgstruct.ConfigFile(configFile), envHome, cfgstruct.SetupMode(), rootDir)
	process.Bind(versionCmd, &struct{}{}, defaults)
	process.Exec(rootCmd)
}

// cmdRun 运行
func cmdRun(cmd *cobra.Command, args []string) (err error) {
	ctx, _ := process.Ctx(cmd)
	_log := log.NewLog(cfg.Log)
	app, fn, err := wire.NewApp(
		ctx,
		cfg.Log,
		cfg.Db,
		cfg.Redis,
		cfg.Jwt,
		cfg.Openapi,
		cfg.RateLimit,
		cfg.Pprof,
		cfg.Api,
		cfg.Payment,
		cfg.Storage,
		cfg.Account,
		cfg.ThirdGame,
		cfg.Notify,
		cfg.Sms,
	)
	if err != nil {
		return err
	}
	defer fn()
	if err = app.Run(ctx); err != nil {
		_log.Error("app.Run error", zap.Error(err))
	}
	return nil
}

// cmdSetup 初始化数据库
func cmdSetup(cmd *cobra.Command, args []string) error {
	return process.SaveConfig(cmd, configFile)
}

// cmdVersion 查看版本信息
func cmdVersion(cmd *cobra.Command, args []string) error {
	if version.Build.Release {
		fmt.Printf("Release version：%s(commit:%s);Release time：%s", version.Build.Version, version.Build.CommitHash, version.Build.Timestamp)
	} else {
		fmt.Printf("Non-release version(commit:%s):%s", version.Build.CommitHash, version.Build.Timestamp)
	}
	return nil
}

// cmdConfig 查看系统配置
func cmdConfig(cmd *cobra.Command, args []string) error {
	fmt.Printf("当前运行环境：[%s]\n", cfgstruct.DefaultsType())
	fmt.Println("当前配置文件路径：", configFile)
	output, _ := json.MarshalIndent(cfg, "", " ")
	fmt.Println(string(output))
	return nil
}
